/* 成员函数运算符重载 */
#include<iostream>
#include<cstring>

using namespace std;

class S
{
	char* p;
	int len;
	S(const S& x);//私有拷贝构造，禁止拷贝
public:
	S(const char* str="")
	{
		len=strlen(str);
		p=new char[len+1];
		strcpy(p,str);
	}
	~S()
	{
		delete[] p;p=NULL;
	}
	S& operator=(const S& x)//重写赋值运算符（因为类中有指针）
	{
		if(&x==this)
			return *this;//自己给自己赋值
		len=x.len;
		delete[] p;//释放旧的内存
		p=new char[len+1];//为p开辟新动态内存
		strcpy(p,x.p);
		return *this;//以当前对象作为复制结果
	}
	friend ostream& operator<<(ostream& o,const S& x)
	{
		return o << x.p;
	}
	char& operator[](int idx)
	{
		/*... 越界检查 */
		return p[idx];
	}
};

int main()
{
	S a,c;
	S b("furong");
	c=a=b;
	cout << a << ' ' << b << ' ' << c << endl;

	cout << a[3] << endl;
	a[1] = 'o';
	cout << a << endl;
	return 0;
}

/* 运算符重载 */
using namespace std;

class P
{
	string name;
	int age;
	float salary;
public:
	P(const char* n,int a,float s)
		:name(n),age(a),salary(s)//参数列表顺序可任意
	{
	}
	operator double()//不写返回类型
	{
		return salary;
	}
	operator int(){return age;}
	operator string(){return name;}
};

int main()
{
	P a("furong",18,80000);
	string info = a;//(string)a,a.operator sting()
	double money = a;
	int age = a;
	cout << info << ' ' << money << ' ' << age << endl;
	return 0;
}

/* 运算符重载 */
#include<iostream>

using namespace std;

class A
{
	int* p;
	int len;
public:
	A(int n,int v=0):p(new int[n]),len(n)
	{
		for(int i=0;i<n;i++)
			p[i]=v;
	}
	void operator()(int start,int step)
	{
		for(int i=0;i<len;i++)
			p[i]=start+i*step;
	}
	int operator()()
	{
		int sum=0;
		for(int i=0;i<len;i++)
			sum+=p[i];
		return sum;
	}
	friend ostream& operator<<(ostream& o,const A& x)
	{
		for(int i=0;i<x.len;i++)
			o << x.p[i] << ' ';
		return o;	
	}
};

int main()
{
	A a(10);
	a(5,1);//从5开始步不长为1填充数组
	/* a.operator()(5,1) */

	cout << a <<endl;
	cout << a() << endl;//a.operator()()
	return 0;
}

/* ->运算符重载 */
#include<iostream>

using namespace std;

struct POINT
{
	int x;
	int y;
};

class Pos
{
	POINT p;
public:
	Pos(int x=0,int y=0)
	{
		p.x=x;
		p.y=y;
	}
	void move(int cx,int cy)
	{
		p.x+=cx;
		p.y+=cy;
	}
	void moveto(int x,int y)
	{
		p.x=x;
		p.y=y;
	}
	POINT* operator->()//->转向p的地址
	{
		return &p;
	}
};

int main()
{
	Pos a(10,20);
	cout << a->x << ',' << a->y << endl;
	a.move(30,-10);
	cout << a->x << ',' << a->y << endl;
	return 0;
}


/* new运算符重载 */
#include<iostream>
#include<cstdlib>

using namespace std;

class A
{
	int data;
	public:
	A(int d=0):data(d)
	{
		cout << "A(" << data << ")" << endl;
	}
	~A()
	{
		cout << "~A(" << data << ")" << endl;
	}
	void* operator new(size_t bytes)
	{
		cout << "bytes=" << bytes << endl;
		return malloc(bytes);
	}
	void operator delete(void* p)
	{
		cout << "free" << p <<endl;
		free(p);
	}
	void* operator new[](size_t bytes)
	{
		cout << "BYTES=" << bytes << endl;
		void* p=malloc(bytes);
		cout << "malloc=" << p << endl;
		return p;
	}
	void operator delete[](void* p)
	{
		cout << "FREE" << p <<endl;
		free(p);
	}
};

int main()
{
	A* p=new A;//operator new(sizeof(A))
	delete p;p=NULL;

	cout << endl;
	p=new A[3];//new和new[]不是同一个运算符
	cout << "神秘数据" << *((int*)p-1) <<endl;//输出藏起来的4个字节
	cout << "p=" << p << endl;
	delete[] p;p=NULL;

	return 0;
}

/* ++/--重载 */
#include<iostream>

using namespace std;

class R
{
	int n;//fen zi
	int d;
	public:
	friend ostream& operator<<(ostream& o,const R& x)
	{
		return o << x.n << '/' << x.d;
	}
	R(int n,int d):n(n),d(d)
	{
	}
	R& operator++()//成员形式的前++
	{
		n += d;
		return *this;
	}
	friend R& operator--(R& x)//友元形式的前--
	{
		x.n -= x.d;
		return x; 
	}
};

int main()
{
	R a(2,3);
	cout << "a=" << ++a << endl;
	//a.operator++()
	cout << "a=" << --a << endl;
	//operator--(a)
	return 0;
}

/* 后++/-- 重载 */
#include<iostream>

using namespace std;

class R
{
	int n;
	int d;
public:
	R(int n=0,int d=1):n(n),d(d)
	{}
	friend ostream& operator<<(ostream& ,const R&);
	R operator++(int)//返回类型不应该加引用
	{//虚假的形参int用于与前++区分，是哑元
		R old=*this;
		n+=d;
		return old;
	}
};

int main()
{
	R a(3,5);
	cout << a++ << endl;//a.operator++(0)后++会传一个无用的参数0
	cout << a << endl;
	return 0;
}

ostream& operator<<(ostream& o,const R& x)
{
	return o << x.n << '/' << x.d;
}

